package com.rtsapp.server.gamelog.analyze.stat.income.LogUtils;

import com.rtsapp.server.gamelog.analyze.stat.MailUtils;
import com.rtsapp.server.gamelog.analyze.stat.StringUtils;

import javax.mail.Address;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by liwang on 17-2-16.
 */
public class LogMonitor {

    private static final long NO_LOG_WARNING_TIME_MINUTE = 30;

    // <gameId, <areaId, <serverId, 最新一条日志的时间>>>
    private final ConcurrentMap<Integer, ConcurrentMap<Integer, ConcurrentMap<Integer, Long>>> gameId_areaId_serverId_recentLogTime_Map = new ConcurrentHashMap<>( );

    private final Map<Integer, Address[]> gameId_addresses_Map = new HashMap<>( );

    private static final LogMonitor instance = new LogMonitor( );

    private LogMonitor( ) {

        // 30分钟没有新日志输入, 发送邮件提醒相关人员
        new Timer( ).scheduleAtFixedRate( new TimerTask( ) {
            @Override
            public void run( ) {

                long timeNow_MS = System.currentTimeMillis( );

                for ( Map.Entry<Integer, ConcurrentMap<Integer, ConcurrentMap<Integer, Long>>> entry3 : gameId_areaId_serverId_recentLogTime_Map.entrySet( ) ) {
                    int gameId = entry3.getKey( );
                    Address[] addresses = gameId_addresses_Map.get( gameId );

                    // 当前gameId的项目没有对应的email地址, 则跳过
                    if ( addresses == null || addresses.length < 1 ) {
                        continue;
                    }

                    for ( Map.Entry<Integer, ConcurrentMap<Integer, Long>> entry2 : entry3.getValue( ).entrySet( ) ) {
                        int areaId = entry2.getKey( );
                        for ( Map.Entry<Integer, Long> entry1 : entry2.getValue( ).entrySet( ) ) {
                            int serverId = entry1.getKey( );
                            long logTime = entry1.getValue( );

                            long noLogTime = ( timeNow_MS - logTime ) / 1000 / 60;
                            if ( noLogTime > NO_LOG_WARNING_TIME_MINUTE ) {
                                String content = "gameId:" + gameId +
                                        "  \nareaId: " + areaId +
                                        "  \nserverId: " + serverId +
                                        "  \n\n已经" + noLogTime + "分钟没有采集到新日志!";

                                // TODO 发送邮件
                                MailUtils.getInstance( ).sendMail( "收入统计异常提醒", content );
                            }
                        }
                    }
                }


            }
        }, 1800000, 1800000 );
    }

    public static LogMonitor getInstance( ) {
        return instance;
    }

    /**
     * 添加一组email
     *
     * @param gameId
     * @param addressesStr
     * @return 添加失败的email地址
     */
    public List<String> addAddresses( int gameId, String... addressesStr ) {

        if ( addressesStr.length < 3 ) {
            return null;
        }

        List<String> failList = null;
        for ( int i = 2; i < addressesStr.length; i++ ) {
            String addressStr = addressesStr[ i ];
            if ( !addAddress( gameId, addressStr ) ) {
                if ( failList == null ) {
                    failList = new ArrayList<>( );
                }
                failList.add( addressStr );
            }
        }

        return failList;
    }

    /**
     * 添加项目负责人email地址
     *
     * @param gameId
     * @param addressStr
     * @return
     */
    public boolean addAddress( int gameId, String addressStr ) {
        if ( StringUtils.isEmpty( addressStr ) ) {
            return false;
        }

        Address[] oldAddresses = gameId_addresses_Map.get( gameId );
        List<Address> newAddressList = oldAddresses == null ? new ArrayList<>( ) : Arrays.asList( oldAddresses );


        try {
            newAddressList.add( new InternetAddress( addressStr ) );
        } catch ( AddressException e ) {
            return false;
        }

        gameId_addresses_Map.put( gameId, newAddressList.toArray( new Address[ newAddressList.size( ) ] ) );

        return true;
    }

    /**
     * 记录新日志时间
     *
     * @param gameId
     * @param areaId
     * @param serverId
     * @param logTime
     */
    public void noteNewLogTime( int gameId, int areaId, int serverId, long logTime ) {
        ConcurrentMap<Integer, ConcurrentMap<Integer, ConcurrentMap<Integer, Long>>> map3 = this.gameId_areaId_serverId_recentLogTime_Map;
        ConcurrentMap<Integer, ConcurrentMap<Integer, Long>> map2 = map3.get( gameId );
        if ( map2 == null ) {
            map2 = new ConcurrentHashMap<>( );
            ConcurrentMap<Integer, ConcurrentMap<Integer, Long>> oldMap = map3.putIfAbsent( gameId, map2 );
            if ( oldMap != null ) {
                map2 = oldMap;
            }
        }

        ConcurrentMap<Integer, Long> map1 = map2.get( areaId );
        if ( map1 == null ) {
            map1 = new ConcurrentHashMap<>( );
            ConcurrentMap<Integer, Long> oldMap = map2.putIfAbsent( areaId, map1 );
            if ( oldMap != null ) {
                map1 = oldMap;
            }
        }

        map1.put( serverId, logTime );
    }


}
